package controllers;

import java.util.List;

import javax.ejb.EJB;
import javax.faces.application.NavigationHandler;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
import javax.faces.event.ComponentSystemEvent;
import javax.servlet.http.HttpSession;

import customExceptions.UserLostRightsException;

import beans.LoginBeanRemote;
import beans.RepositoryBeanRemote;
import beans.UserBeanRemote;

import dto.DTOUser;
import dto.RepositoryDTO;

/**
 * 
 * Controller used for security purposes. Has three main methods, one for each type of user: simple, supervisor and admin.
 * 
 * @author ciobanm
 *
 */
@ManagedBean(name="security")
@SessionScoped
public class SecurityController {
	
	@ManagedProperty(value="#{dTOUser}")
	private DTOUser currentUser;
	
	@ManagedProperty(value = "#{repositoryDTO}")
	RepositoryDTO currentRepository;
	
	@EJB
	RepositoryBeanRemote rbr;
	
	@EJB
	LoginBeanRemote lbr;
	
	@EJB
	UserBeanRemote ubr;

	public RepositoryDTO getCurrentRepository() {
		return currentRepository;
	}
	public void setCurrentRepository(RepositoryDTO currentRepository) {
		this.currentRepository = currentRepository;
	}
	public DTOUser getCurrentUser() {
		return currentUser;
	}
	public void setCurrentUser(DTOUser currentUser) {
		this.currentUser = currentUser;
	}
	
	/**
	 * Method that makes simple user specific checks 
	 * 
	 * @param event
	 */
	public void checkSimpleUserCredentials(ComponentSystemEvent event) {
		FacesContext fc = FacesContext.getCurrentInstance();
		HttpSession session = (HttpSession) fc.getExternalContext().getSession(false);
		NavigationHandler nav = fc.getApplication().getNavigationHandler();
		
		String destinationAddress = null;
		
		if (!isUserLogged()) {
			destinationAddress = "/login.xhtml";
		} else {
			if (isUserInvalidated()) {
				destinationAddress = "/errorLogin.xhtml";
				session.setAttribute("errorMessageNumber", 1);
			}
		}
		
		nav.handleNavigation(fc, null, destinationAddress);
	}
	
	/**
	 * Method that makes supervisor specific checks 
	 * 
	 * @param event
	 */
	public void checkSupervisorCredentials(ComponentSystemEvent event) {
		FacesContext fc = FacesContext.getCurrentInstance();
		HttpSession session = (HttpSession) fc.getExternalContext().getSession(false);
		NavigationHandler nav = fc.getApplication().getNavigationHandler();
		
		String destinationAddress = null;
		
		if (!isUserLogged()) {
			destinationAddress = "/login.xhtml";
		} else {
			if (!isSupervisorOnCurrentRepository()) {
				destinationAddress = "/userPage.xhtml";
			} else {
				if (isSupervisorNoLonger()) {
					destinationAddress = "/errorLogin.xhtml";
					session.setAttribute("errorMessageNumber", 2);
				}
			}
			if (isUserInvalidated()) {
				destinationAddress = "/errorLogin.xhtml";
				session.setAttribute("errorMessageNumber", 1);
			}
		}
		
		nav.handleNavigation(fc, null, destinationAddress);
		
	}
	
	/**
	 * Method that makes admin specific checks 
	 * 
	 * @param event
	 */
	public void checkAdminCredentials(ComponentSystemEvent event) {
		FacesContext fc = FacesContext.getCurrentInstance();
		NavigationHandler nav = fc.getApplication().getNavigationHandler();
		
		String destinationAddress = null;
		
		if (!isUserLogged()) {
			destinationAddress = "/login.xhtml";
		} else {
			if (isSimpleUser()) {
				if (isSupervisorOnCurrentRepository()) {
					destinationAddress = "/supervisorPage.xhtml";
				} else {
					destinationAddress = "/userPage.xhtml";
				}
			}
		}
		
		nav.handleNavigation(fc, null, destinationAddress);
	}
	
	private boolean isSimpleUser() {
		boolean isSimpUser = false;
		
		if (currentUser.getType().equals("user")) {
			isSimpUser = true;
		}
		
		return isSimpUser;
	}
	
	private boolean isSupervisorOnCurrentRepository() {
		boolean isSupervisor = false;
		
		if (currentRepository.getSupName().equals(currentUser.getName())) {
			isSupervisor = true;
		}
		
		return isSupervisor;
	}
	
	private boolean isSupervisorNoLonger() {
		boolean supervisorNoLonger = false;
		
		String supervisor = lbr.findSupervisor(currentRepository.getId());
		
		if (!supervisor.equals(currentUser.getName())) {
			supervisorNoLonger = true;
		}
		
		return supervisorNoLonger;
	}
	
	private boolean isUserLogged() {
		boolean isLogged = true;
		
		if (currentUser.getId() == null) {
			isLogged = false;
		}
		
		return isLogged;
	}
	
	private boolean isUserInvalidated() {
		boolean userInvalidated = false;
		
		currentUser = ubr.getUser(currentUser.getId());
		if ( currentUser.getType().equals("invalidated") ) {
			userInvalidated = true;
		}
		
		return userInvalidated;
	}
	
}
